module scene.scene;

import std.datetime;

import mirgame;

import share.container, share.types;


public enum SceneType
{
    Intro, Login, SelectServer,
    SelectChr, NewChr, Loading,
    LoginNotice, PlayGame
}

public abstract class Scene
{
    public SceneType sceneType;
    public Game game;

    public this(Game game, SceneType scenetype)
    {
        this.game = game;
        this.sceneType = scenetype;
    }

    public void Initialize() { }
    public void Finalize() { }
    public void OpeningScene() { }	
    public void OpenScene() { }
    public void CloseScene() { }
    public void PlayScene() { }
	public void UpdateScene() { }

    public void MouseMove(in IntPoint pt) { }
    public void MouseDown(uint button, in IntPoint pt) { }
    public void MouseUp(uint button, in IntPoint pt) { }
    public void KeyDown(int keycode) { }
    public void KeyUp(int keycode) { }
}


public final class SceneManager
{
	public Scene CurrentScene;
    public Vector!Scene SceneList;
	
	// Frame Rate..
	/*private TickDuration LastTime;
	private TickDuration LastFrameTime;
	private int FrameRate;
	private int FramesPerSecond;*/
	private TickDuration LastTime;
	private int LastFrameRate;
	private int FrameRate;


	public @property int CurrentFPS() const nothrow
    {
		return LastFrameRate;
    }

	public this()
	{
		/*LastTime = Clock.currSystemTick();
		LastFrameTime = TickDuration.init;
		FrameRate = 0;
		FramesPerSecond = 0;*/
		LastTime = Clock.currSystemTick();
		LastFrameRate = 0;
		FrameRate = 0;
		
		CurrentScene = null;
	}
    
    public void AddScene(Scene s)
    {
        if (s !is null)
        {
            SceneList.add(s);
        }
    }
    
    public void RemoveScene(Scene s, bool closeAndFinish = false)
    {
        if (s !is null)
        {
            if (CurrentScene is s)
            {
                if (closeAndFinish)
                {
                    CurrentScene.CloseScene();
                    CurrentScene.Finalize();
                }
                CurrentScene = null;
            }
            
            int index = SceneList.indexOf(s);
            if (index >= 0)
                SceneList.deleteAt(index);
        }
    }

	public void Initialize()
	{
		if (CurrentScene !is null)
			CurrentScene.Initialize();
	}

	public void Finalize()
	{
		if (CurrentScene !is null)
			CurrentScene.Finalize();
	}

	public void ChangeScene(SceneType st)
	{
		if (CurrentScene !is null)
			CurrentScene.CloseScene();
		
		Finalize();

        for (int i = 0; i < SceneList.count; i++)
        {
            Scene se = SceneList[i];
            if (st == se.sceneType)
            {
                CurrentScene = se;
                break;
            }
        }

		Initialize();
		
		if (CurrentScene !is null)
			CurrentScene.OpenScene();
	}

	public void RunScene()
	{
		// TODO: we could clear the scene here!!
		//MSurface.Fill(0);

		if (CurrentScene !is null)
			CurrentScene.PlayScene();
	}
	
	public void UpdateScene()
	{
		// TODO: we could clear the scene here!!
		//MSurface.Fill(0);

		if (CurrentScene !is null)
			CurrentScene.UpdateScene();
	}

	/// <summary>
	/// Calculates the frame rate for the game.
	/// </summary>
	/// <returns>Frame rate since last pass.</returns>
	public void CalculateFrameRate()
	{
		TickDuration time = Clock.currSystemTick;
		
		if ((time - LastTime).msecs >= 1000)
		{
			LastTime = time;
			LastFrameRate = FrameRate;
			FrameRate = 0;
		}
		FrameRate++;

		
		/*TickDuration time = Clock.currSystemTick;
		
		FrameRate++;
		
		if ((time - LastTime).msecs > 1000)
		{
			FramesPerSecond = cast(int)(FrameRate / ( (time - LastTime).msecs / 1000 ));
			LastTime = time;
			FrameRate = 0;
		}*/
	}
	
    public void MouseMove(in IntPoint pt)
	{
		if (CurrentScene !is null)
            CurrentScene.MouseMove(pt);
	}

    public void MouseDown(uint button, in IntPoint pt)
	{
		if (CurrentScene !is null)
            CurrentScene.MouseDown(button, pt);
	}

    public void MouseUp(uint button, in IntPoint pt)
	{
		if (CurrentScene !is null)
            CurrentScene.MouseUp(button, pt);
	}

    public void KeyDown(int keycode)
    {
        if (CurrentScene !is null)
            CurrentScene.KeyDown(keycode);
    }

    public void KeyUp(int keycode)
    {
        if (CurrentScene !is null)
            CurrentScene.KeyUp(keycode);
    }
}